// 这块是 路由前置导航守卫 的逻辑, 这块逻辑我们自己写
import router from '@/router'
import store from './store'
import NProgress from 'nprogress' // 引入一份进度条插件
import 'nprogress/nprogress.css' // 引入进度条样式
import { asyncRoutes } from '@/router'

// 设定无需授权, 即可访问的页面: 白名单
const whiteList = ['/login', '/404']

// 利用 NProgress 可以给页面路由的访问, 添加一个进度条效果,
// 当真正进入到页面时, 才关闭加载中的效果
// NProgress.start()
// setTimeout(() => {
//   NProgress.done()
// }, 3000)

// 需求:
// 1. 准备要进入某个页面, 还在守卫这里, 守卫这里开进度条
// 2. 完全进入到页面, 关进度条
// 目前, 守卫这里进行的不是耗时的动作, 进度条的效果就不明显
// 将来, 守卫这里会进行一些耗时请求判断, 加了这个进度条效果, 将来会很明显, 很好看~

// 全局前置守卫: 在页面路由被真正匹配解析之前, 先会经过前置守卫~
router.beforeEach(async(to, from, next) => {
  // 一到守卫的位置, 立刻开启进度条
  NProgress.start()
  // token要在导航守卫中实时获取, getters
  const token = store.getters.token
  if (token) {
    if (to.path === '/login') {
      next('/') // 有身份的用户直接去首页
      NProgress.done() // 拦截之后手动关闭
    } else {
      // 这里的判断表示：个人信息，包括权限设置，来回切换页面，只需要设置一次
      if (!store.getters.userId) {
        const { roles: { menus }} = await store.dispatch('user/getUserInfo')
        // 在这里基于权限标识，将所有的动态路由进行过滤，过滤出用户需要的路由展示

        // menus asyncRoutes
        const resRoutes = asyncRoutes.filter(item => {
          // 看模块的唯一标识，是否出现在了权限菜单数组中，如果有说明该权限开放了
          return menus.includes(item.children[0].name)
        })

        router.addRoutes([
          ...resRoutes,
          { path: '*', redirect: '/404', hidden: true }
        ])
        store.commit('permission/setRoutes', resRoutes)

        // 上面路由权限变化了，而此时生效的还是旧的路由，希望生效的是新的路由
        // push('/login')  push({ xxx })
        // next('/login')  next({ xxx })
        next({
          ...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
          replace: true // 重进一次, 不保留重复历史
        })
        return
      }
      next() // 正常放行(重新进一次页面时，走这里正常方向，生效的已经是正确的路由了)
    }
  } else {
    // 2. token不存在, 看访问的是不是白名单中地址
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login')
      NProgress.done() // 拦截之后手动关闭
    }
  }
})

// 全局后置守卫: 此时路由页面已经解析后, 触发后置守卫
router.afterEach((to, from) => {
  setTimeout(() => {
    // 统一的关闭进度条
    NProgress.done()
  }, 1000)
})

